﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using System;
using System.Collections.Generic;
using System.Linq;

namespace Caffeine.Core.Test.TestModel
{
    public class ModelForMetadataTestingC : ModelBase
    {
        private readonly ModelProperty<String> _stringProperty;
        private readonly ModelProperty<Int32> _intProperty;
        private readonly ModelProperty<Nullable<Int32>> _nullableIntProperty;
        private readonly ModelProperty<EnumForTesting> _enumProperty;
        private readonly ModelProperty<Nullable<EnumForTesting>> _nullableEnumForTesting;
        private readonly ModelProperty<ModelForMetadataTestingC> _childModel;
        private readonly ModelProperty<Object> _objectProperty;
        private readonly ModelProperty<String> _fullNameProperty;
        private readonly ModelProperty<String> _firstNameProperty;
        private readonly ModelProperty<String> _lastNameProperty;

        public ModelForMetadataTestingC()
        {
            _stringProperty = RegisterProperty<String>("StringProperty");
            _intProperty = RegisterProperty<Int32>("IntProperty");
            _nullableIntProperty = RegisterProperty<Nullable<Int32>>("NullableIntProperty");
            _enumProperty = RegisterProperty<EnumForTesting>("EnumProperty");
            _nullableEnumForTesting = RegisterProperty<Nullable<EnumForTesting>>("NullableEnumForTesting");
            _childModel = RegisterProperty<ModelForMetadataTestingC>("ChildModel");
            _objectProperty = RegisterProperty<Object>("ObjectProperty");
            _firstNameProperty = RegisterProperty<String>("FirstNameProperty");
            _lastNameProperty = RegisterProperty<String>("LastNameProperty");
            _fullNameProperty = RegisterComputedProperty<String>
            (
                "FullNameProperty",
                ComputeFullName,
                FirstNameProperty,
                LastNameProperty
            );
        }

        protected override void OnInitialized()
        {
            base.OnInitialized();
            StringProperty.ValidationMethod = ValidateProperty;
            IntProperty.ValidationMethod = ValidateProperty;
            NullableIntProperty.ValidationMethod = ValidateProperty;
            EnumProperty.ValidationMethod = ValidateProperty;
            NullableEnumForTesting.ValidationMethod = ValidateProperty;
            ChildModel.ValidationMethod = ValidateProperty;
            ObjectProperty.ValidationMethod = ValidateProperty;
            FullNameProperty.ValidationMethod = ValidateProperty;
            FirstNameProperty.ValidationMethod = ValidateProperty;
            LastNameProperty.ValidationMethod = ValidateProperty;
        }

        public ModelProperty<String> StringProperty
        {
            get { return _stringProperty; }
        }

        public ModelProperty<Int32> IntProperty
        {
            get { return _intProperty; }
        }

        public ModelProperty<Nullable<Int32>> NullableIntProperty
        {
            get { return _nullableIntProperty; }
        }

        public ModelProperty<EnumForTesting> EnumProperty
        {
            get { return _enumProperty; }
        }

        public ModelProperty<Nullable<EnumForTesting>> NullableEnumForTesting
        {
            get { return _nullableEnumForTesting; }
        }

        public ModelProperty<ModelForMetadataTestingC> ChildModel
        {
            get { return _childModel; }
        }

        public ModelProperty<Object> ObjectProperty
        {
            get { return _objectProperty; }
        }

        public ModelProperty<String> FullNameProperty
        {
            get { return _fullNameProperty; }
        }

        public ModelProperty<String> FirstNameProperty
        {
            get { return _firstNameProperty; }
        }

        public ModelProperty<String> LastNameProperty
        {
            get { return _lastNameProperty; }
        }

        private static String ComputeFullName(IEnumerable<ModelProperty<String>> properties, String currentValue)
        {
            ModelProperty<String> firstName = properties.Single(property => property.Name == "FirstNameProperty");
            ModelProperty<String> lastName = properties.Single(property => property.Name == "LastNameProperty");
            return String.Format("{0}, {1}", lastName.Value, firstName.Value);
        }

        private static void ValidateProperty<T>(ModelProperty<T> property, ref IEnumerable<ValidationError> errors, ref Boolean isValid)
        {
            isValid = !property.IsDirty;

            if (property.IsDirty)
            {
                List<ValidationError> errorCollection = new List<ValidationError>();
                errorCollection.Add(new ValidationError() { ErrorCode = 1, ErrorDescription = "Error1" });
                errorCollection.Add(new ValidationError() { ErrorCode = 2, ErrorDescription = "Error2" });
                errors = errorCollection;
            }
        }
    }
}
